#include "Connection.h"
#include "Logger.h"
Connection::Connection(EventLoop *loop, uint64_t conn_id, int sockfd)
    : _conn_id(conn_id), _sockfd(sockfd), _enable_inactive_release(false),
      _loop(loop),
      _statu(CONNECTING),
      _socket(sockfd),
      _channel(loop, _sockfd)
{
    _channel.SetReadCallback(std::bind(&Connection::HandleRead, this));
    _channel.SetWriteCallback(std::bind(&Connection::HandleWrite, this));
    _channel.SetCloseCallback(std::bind(&Connection::HandleClose, this));
    _channel.SetErrorCallback(std::bind(&Connection::HandleError, this));
    _channel.SetEventCallback(std::bind(&Connection::HandleEvent, this));
}

Connection::~Connection()
{
    DBG_LOG("释放连接: %p", this);
}

void Connection::HandleRead()
{
    // 读事件回调函数：当 socket 可读时由 EventLoop 触发。
    // 从 socket 读取数据到 _in_buffer 缓冲区。
    // 如果读取成功，则调用上层设置的 _message_callback 回调处理数据。
    // 如果返回 0 表示客户端关闭连接，则调用 HandleClose() 关闭连接。
    // 如果读取失败（错误码 < 0），调用 HandleError() 进行异常处理。
    char buf[65536];
    ssize_t ret = _socket.NonBlockRecv(buf, 65535);
    if (ret < 0)
    {
        // 读取出错了，可能是客户端关闭，不能直接关闭，因为可能有数据没有发送或者有数据还没有处理
        return ShutdownInLoop();
    }
    else if (ret == 0)
    {
        // 表示没有接收到数据，并不是连接断开
        return;
    }
    _in_buffer.WriteAndPush(buf, ret);
    // 调用message_callback进行业务处理
    if (_in_buffer.ReadAbleSize() > 0)
    {
        _message_callback(shared_from_this(), &_in_buffer);
    }
}

void Connection::HandleWrite()
{
    // 写事件回调函数：当 socket 可写时由 EventLoop 调用。
    // 一般由上层调用 Send() 时，若数据未能一次性写完，
    // 会将剩余数据保存到 _out_buffer，并注册写事件监听。
    // 当 epoll 通知 socket 可写时，触发本函数继续发送剩余数据。
    // 如果数据全部发送完成，则关闭写事件监听（避免空转）。
    // 如果连接正处于 DISCONNECTING 状态，并且数据也发送完了，
    // 则释放连接资源。
    ssize_t ret = _socket.NonBlockSend(_out_buffer.ReadPosition(), _out_buffer.ReadAbleSize());
    if (ret < 0)
    {
        // 发送错误，关闭连接
        if (_in_buffer.ReadAbleSize() > 0) // 接收缓冲区还有数据，得处理了
        {
            _message_callback(shared_from_this(), &_in_buffer);
        }
        return Release();
    }
    _out_buffer.MoveReadOffset(ret);
    if (_out_buffer.ReadAbleSize() == 0) // 表示数据发生完成了，就关闭写事件监控
    {
        _channel.DisableWrite();
        // 如果当前连接是待关闭状态，并且数据发送完成了，则可以将连接直接释放
        if (_statu == DISCONNECTING)
            return Release();
    }
    return;
}

void Connection::HandleClose()
{
    // 关闭事件回调：表示对端关闭了连接（如返回 0 字节）。
    // 触发 _close_callback 由上层进行连接资源释放。
    // 通常在读取返回 0 字节时调用（即对端正常关闭）。
    // 一旦连接挂断了，套接字就什么都不干了，因此有数据待处理就处理一下，完毕关闭连接
    if (_in_buffer.ReadAbleSize() > 0)
    {
        _message_callback(shared_from_this(), &_in_buffer);
    }
    return Release();
}

void Connection::HandleError()
{
    // 错误事件回调：在连接出现错误（如读写错误、EPOLLERR 等）时触发。
    // 通常直接调用 Release() 释放连接资源。
    return HandleClose();
}

// 只有有任意事件触发了，都要调用这个函数
void Connection::HandleEvent()
{
    // 1. 刷新连接活跃度
    if (_enable_inactive_release == true)
    {
        _loop->TimerRefresh(_conn_id);
    }
    // 调用组件使用者的任意事件回调
    if (_event_callback)
        _event_callback(shared_from_this());
}

// 是在服务器 accept() 得到新连接后，把连接绑定到某个子线程的 EventLoop 中，并注册读事件，正式加入事件驱动模型的入口函数。
void Connection::EstablishedInLoop()
{
    // 1. 修改连接状态
    assert(_statu == CONNECTING); // 当前状态移动是半连接状态
    _statu = CONNECTED;           // 设置为已连接状态
    _channel.EnableRead();
    if (_connected_callback)
        _connected_callback(shared_from_this());
}

//  实际的释放接口
void Connection::ReleaseInLoop()
{
    // 1). 修改连接状态,将其设置为DISCONNECTED
    _statu = DISCONNECTED;
    // 2). 移除连接的事件监控
    _channel.Remove();
    // 3). 关闭描述符
    _socket.Close();
    // 4). 如果当前定时器队列中还有定时任务，则取消任务
    if (_loop->HasTimer(_conn_id))
        CancelInactiveRelease();
    // 5. 调用关闭回调函数，避免先移除服务器管理连接信息吊装Connectiotion被释放，因此先调用用户的回调函数
    if (_closed_callback)
        _closed_callback(shared_from_this());
    if (_server_closed_callback)
        _server_closed_callback(shared_from_this());
}

//这个接口并不是实际的发送接口，而只是把数据放到了发送缓冲区，启动了可写事件监控
//为什么要这么做？因为可写条件可能不就绪，即内核缓冲区的数据满了，写不进去了
void Connection::SendInLoop(Buffer buf)
{
    // 1). 如果连接已经关闭，则直接return
    if (_statu == DISCONNECTED)
        return;
    _out_buffer.WriteBufferAndPush(buf);
    if (_channel.WriteAble() == false)
        _channel.EnableWrite();
}

//
void Connection::ShutdownInLoop()
{
    // 关闭连接写端的回调函数，需在连接所属的事件循环线程中执行。
    // 如果当前发送缓冲区为空，立即调用 shutdown() 关闭写端；
    // 否则将连接状态设置为 DISCONNECTING，等待发送缓冲区清空后再关闭。
    // 这是实现 TCP 连接优雅关闭（graceful shutdown）的关键步骤，
    // 可避免数据丢失或过早关闭导致的异常。
    _statu = DISCONNECTING;            // 半关闭状态
    if (_in_buffer.ReadAbleSize() > 0) // 用户层接收缓冲区还有数据，要处理数据
    {
        if (_message_callback)
            _message_callback(shared_from_this(), &_in_buffer);
    }
    // 用户层发送缓冲区还有数据，得把数据发送出去，再关闭
    if (_out_buffer.ReadAbleSize() > 0)
    {
        if (_channel.WriteAble() == false)
            _channel.EnableWrite();
    }
    if (_out_buffer.ReadAbleSize() == 0)
        Release();
}

// 启动非活跃连接释放规则
void Connection::EnableInactiveReleaseInLoop(int sec)
{
    // 将判断标志位设为true
    _enable_inactive_release = true;
    // 如果当前定时销毁任务已经存在，那就延迟刷新一下
    if (_loop->HasTimer(_conn_id))
        return _loop->TimerRefresh(_conn_id);
    // 如果不存在定时销毁任务，就新增
    _loop->TimerAdd(_conn_id, sec, std::bind(&Connection::Release, this));
}

// 取消非活跃连接释放
void Connection::CancelInactiveReleaseInLoop()
{
    _enable_inactive_release = false;
    if (_loop->HasTimer(_conn_id))
        _loop->TimerCancel(_conn_id);
}

// 切换协议/升级协议
void Connection::UpgradeInLoop(const Any &context,
                               const ConnectedCallback &conn,
                               const MessageCallback &msg,
                               const ClosedCallback &closed,
                               const AnyEventCallback &event)
{
    _context = context; // 改变上下文
    _connected_callback = conn;
    _message_callback = msg;
    _closed_callback = closed;
    _event_callback = event;
}

// 获取当前连接的描述符
int Connection::Fd()
{
    return _sockfd;
}

// 获取连接ID
int Connection::Id()
{
    return _conn_id;
}

// 是否处于CONNECTED状态
bool Connection::Connected()
{
    return (_statu == CONNECTED);
}

// 设置上下文 --- 连接建立完成时进行调用
void Connection::SetContext(const Any &context)
{
    _context = context;
}

// 获取上下文 ，返回的是指针
Any *Connection::GetContext()
{
    return &_context;
}

void Connection::SetConnectedCallback(const ConnectedCallback &cb)
{
    _connected_callback = cb;
}
void Connection::SetMessageCallback(const MessageCallback &cb)
{
    _message_callback = cb;
}
void Connection::SetClosedCallback(const ClosedCallback &cb)
{
    _closed_callback = cb;
}
void Connection::SetSvrClosedCallback(const ClosedCallback &cb)
{
    _server_closed_callback = cb;
}
void Connection::SetAnyEventCallback(const AnyEventCallback &cb)
{
    _event_callback = cb;
}

// 连接建立之后，就绪channel回调，启动监控，调用_connected_callback
void Connection::Established()
{
    _loop->RunInLoop(std::bind(&Connection::EstablishedInLoop, this));
}

// 发送数据，将数据放到发送缓冲区(用户层)
void Connection::Send(const char *data, size_t len)
{
    Buffer buf;
    buf.WriteAndPush(data, len);
    _loop->RunInLoop(std::bind(&Connection::SendInLoop, this, std::move(buf)));
}

// 提供给组件使用者的关闭接口 -- 并不实际关闭，需要判断有没有数据待处理
void Connection::ShutDown()
{
    _loop->RunInLoop(std::bind(&Connection::ShutdownInLoop, this));
}

void Connection::Release()
{
    _loop->QueueInLoop(std::bind(&Connection::ReleaseInLoop, this));
}

//启动非活跃销毁，并定义多长时间无通信就是非活跃，添加定时任务
void Connection::EnableInactiveRelease(int sec)
{
    _loop->RunInLoop(std::bind(&Connection::EnableInactiveReleaseInLoop, this, sec));
}
// 取消非活跃销毁
void Connection::CancelInactiveRelease()
{
    _loop->RunInLoop(std::bind(&Connection::CancelInactiveReleaseInLoop, this));
}
//切换协议 -- 重置上下文以及阶段性处理函数
void Connection::Upgrade(const Any &context,
                         const ConnectedCallback &conn,
                         const MessageCallback &msg,
                         const ClosedCallback &closed,
                         const AnyEventCallback &event)
{
    _loop->RunInLoop(std::bind(&Connection::UpgradeInLoop, this, context, conn, msg, closed, event));
}
